package socketmvc.core.codec;

import socketmvc.core.util.BytesUtils;
import socketmvc.core.util.JsonKit;
import socketmvc.core.exception.DecodeBufferLen0Exception;
import socketmvc.core.packets.basic.IPacket;
import socketmvc.core.packets.basic.Protocol;
import socketmvc.core.packets.basic.impl.JsonBinPacket;
import socketmvc.core.packets.basic.impl.JsonTextBody;

import java.nio.ByteBuffer;
import java.util.Optional;

public class JsonTextBinContentCodec extends AbstractCodec{

    protected final int HEADER_LENGTH = 9;

    /**
     * 解码
     *
     * @param buffer bytes
     * @return packet
     */
    @Override
    public IPacket decode(ByteBuffer buffer) {
        int readableLength = getBufferReadableLength(buffer);
        // 数据包可读长度小于5，证明数据不够（5代表协议头部有5bytes,1byte协议版本号码，4byte报文内容的长度）
        if (readableLength < HEADER_LENGTH){
            return null;
        }
        byte version = buffer.get(); // 1byte版本号
        int textBodyLen = buffer.getInt(); // 文本内容长度
        int binBodyLen = buffer.getInt(); // 二进制内容长度
        if (textBodyLen <= 0){
            // 抛出协议异常
            throw new DecodeBufferLen0Exception();
        }
        //计算本次需要的数据长度
        int neededLength = HEADER_LENGTH + textBodyLen + binBodyLen;
        //收到的数据是否足够组包
        int isDataEnough = readableLength - neededLength;

        if (isDataEnough >= 0) { //组包成功
            byte[] textBodyBytes = new byte[textBodyLen];
            buffer.get(textBodyBytes);
            byte[] binBodyBytes = new byte[binBodyLen];
            buffer.get(binBodyBytes);
            return createPacket(textBodyBytes,binBodyBytes);
        }

        return null;

    }

    /**
     * 创建协议包
     * @param textBodyBytes 文本内容
     * @param binBodyBytes 二进制内容
     * @return packet
     */
    protected IPacket createPacket(byte[] textBodyBytes,byte[] binBodyBytes){
        return new JsonBinPacket(
                JsonKit.toBean(BytesUtils.bytesToString(textBodyBytes), JsonTextBody.class),binBodyBytes);
    }

    /**
     * 编码
     *
     * @param packet packet
     * @return bytes
     */
    @Override
    public ByteBuffer encode(IPacket packet) {
        byte version = packet.protocolVersion();
        byte[] textBodyBytes = BytesUtils.stringToBytes(packet.getTextBodyAsStr());
        byte[] binBodyAsBytes = Optional.ofNullable(packet.getBinBodyAsBytes()).orElse(new byte[0]);
        // 4byte 文本段正文长度
        int textBodyLength = textBodyBytes.length;
        // 4byte 二进制段正文长度
        int binBodyLength = binBodyAsBytes.length;

        int allLength = HEADER_LENGTH + textBodyLength + binBodyLength;
        ByteBuffer buffer = ByteBuffer.allocate(allLength);
        buffer.put(version);  // 1byte协议版本号
        buffer.putInt(textBodyLength); // 4byte 文本段正文长度
        buffer.putInt(binBodyLength); // 4byte 二进制段正文长度
        buffer.put(textBodyBytes); // n byte 文本段正文
        buffer.put(binBodyAsBytes); // n byte 二进制段正文
        return buffer;
    }

    /**
     * 当前解析器所属协议
     *
     * @return 协议对象
     */
    @Override
    public byte protocolVersion() {
        return Protocol.JSON_TEXT_BIN_CONTENT.getVersion();
    }
}
